package org.qiyu.live.im.core.server.handler.impl;

import com.alibaba.fastjson2.JSON;
import io.netty.channel.ChannelHandlerContext;
import jakarta.annotation.Resource;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.qiyu.live.im.constants.AppIdEnum;
import org.qiyu.live.im.constants.ImMsgCodeEnum;
import org.qiyu.live.im.core.server.common.ChannelHandlerContextCache;
import org.qiyu.live.im.core.server.common.ImContextUtils;
import org.qiyu.live.im.core.server.common.ImMsg;
import org.qiyu.live.im.core.server.handler.SimplyHandler;
import org.qiyu.live.im.dto.ImMsgBody;
import org.qiyu.live.im.interfaces.ImTokenRpc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

/**
 *
 * 登录消息的处理逻辑统一收拢到这个类中
 * 作者：無言
 * 时间：2024/12/2 21:34
 * 描述：永无BUG
 */
@Component
public class LoginMsgHandler implements SimplyHandler {
    private static final Logger LOGGER = LoggerFactory.getLogger(LoginMsgHandler.class);

    @DubboReference
    private ImTokenRpc imTokenRpc;

    @Override
    public void handler(ChannelHandlerContext ctx, ImMsg imMsg) {
        byte[] body = imMsg.getBody();
        if(body == null || body.length == 0) {
            LOGGER.error("[login] body is null, imMsg is {}", imMsg);
            throw new IllegalArgumentException("body is error");
        }

        ImMsgBody imMsgBody = JSON.parseObject(new String(body), ImMsgBody.class);
        Long userIdFromMsg = imMsgBody.getUserId();
        Integer appId = imMsgBody.getAppId();
        String token = imMsgBody.getToken();
        if (StringUtils.isEmpty(token) || userIdFromMsg < 10000 || appId < 10000) {
            ctx.close();
            LOGGER.error("param error,imMsg is {}", imMsg);
            throw new IllegalArgumentException("param error");
        }

        Long userId = imTokenRpc.getUserIdByToken(token);
        //token校验成功，允许建立连接，并将数据会写到客户端，相当于返回一个ack消息
        if(userId != null && userId.equals(imMsgBody.getUserId())) {
            //建立连接后，将用户对应的channel和userId关联起来，并保存好
            ChannelHandlerContextCache.put(userId, ctx);

            //将用户信息和channel信息保存起来,相当于把信息设置到netty上下文中，实现信息的获取和设置
            ImContextUtils.setUserId(ctx, userId);

            //im消息会写给客户端
            ImMsgBody responseBody = new ImMsgBody();
            responseBody.setAppId(AppIdEnum.QIYU_LIVE_BIZ.getCode());
            responseBody.setUserId(userId);
            responseBody.setData("true");
            ImMsg respMsg = ImMsg.build(ImMsgCodeEnum.IM_LOGIN_MSG.getCode(), JSON.toJSONString(responseBody));
            LOGGER.info("[LoginMsgHandler] login success,userId is {},appId is {}", userId, appId);
            ctx.writeAndFlush(respMsg);
        }
        ctx.close();
        LOGGER.error("[login] token check is error, imMsg is {}", imMsg);
        throw new IllegalArgumentException("token check is error");
    }
}
